/**
 * Created by lmn98 on 2017/5/20.
 */

var WebTorrent = require('webtorrent');
var clients = {};
var db = require('./my_sequlize');
var err = require('./error');
var conf = require('../config');
var queue = {
    push: function (username, infoHash, downloadCb, waitCb) {
        db.torrent.count({
            include: [{
                model: db.user,
                where: {
                    username: username
                }
            }],
            where: {
                state: 0
            }
        }).then(function (count) {
            if(count > conf.torrent.limit) {
                db.torrent.update({
                    state: 4 //0 ing, 1 pause, 2 finish, 3 deleted, 4 waitting
                },{
                    where: {
                        infoHash: infoHash
                    }
                }).then(function () {
                    waitCb();
                });
            }else
                downloadCb();
        });
    },
    pull: function (username, cb) {
        db.torrent.find({
            include: [{
                model: db.user,
                where: {
                    username: username
                }
            }],
            where: {
                state: 4
            },
            order: 'updatedAt desc'
        }).then(function (tor) {
            if(tor){
                findOneTorrentFromInfoHash(username, tor.infoHash, function (torrent) {
                    if(torrent.error) cb();
                    else{
                        torrent.resume();
                        db.torrent.update({
                            state: 0
                        },{
                            where: { infoHash: t.infoHash}
                        }).then(function () {
                            cb();
                        })
                    }
                });
            }else cb();
        })
    }
};
var findOneTorrentFromInfoHash = function (username, infoHash, cb) {
    if(clients[username].torrents.length ===0) cb(err.fileNotExist);
    var found = false;
    clients[username].torrents.forEach(function (e,i) {
        if(e.infoHash === infoHash){
            found = true;
            cb(e)
        }else if(!found && i+1 === clients[username].torrents.length)
            cb(err.fileNotExist);
    });
};

module.exports = {
    start: function (username) {
        if(!clients.hasOwnProperty(username)){
            clients[username] =  new WebTorrent();
            clients[username].on('error', function (err) {
                console.log(err)
            })
        }
    },
    add: function (username, dir, savePath, cb) {
        if(!clients.hasOwnProperty(username)){
            cb(err.serverErr);
            return;
        }
        clients[username].add(dir,{
            path: savePath
        },function (tor) {
            tor.on('done', function () {
                db.torrent.update({
                    state: 2 //0 ing, 1 pause, 2 finish, 3 deleted, 4 waitting
                },{
                    where: {
                        infoHash: tor.infoHash
                    }
                });
                tor.destroy();
            });
            queue.push(username, tor.infoHash, function () {
                cb({state:0})
            }, function () {
                tor.pause();
                cb({state: 4});
            });
        });
    },
    pause: function (username, infoHash, cb) {
        if(!clients.hasOwnProperty(username)){
            cb(err.serverErr);
            return;
        }
        findOneTorrentFromInfoHash(username, infoHash, function (torrent) {
            if(torrent.error) cb(torrent);
            else {
                torrent.pause();
                db.torrent.update({
                    state: 1
                },{
                    where: { infoHash: infoHash}
                }).then(function () {
                    queue.pull(username, function () {
                        cb({state: 1});
                    });
                });
            }
        });
    },
    resume: function (username, infoHash, cb) {
        if(!clients.hasOwnProperty(username)){
            cb(err.serverErr);
            return;
        }
        queue.push(username, infoHash, function () {
            findOneTorrentFromInfoHash(username, infoHash, function (torrent) {
                if(torrent.error) cb(torrent);
                else {
                    torrent.resume();
                    db.torrent.update({
                        state: 0
                    }, {
                        where: {infoHash: infoHash, state: 1}
                    }).then(function () {
                        cb({state: 0});
                    });
                }
            });
        }, function () {
            cb({state: 4});
        });
    },
    destroy: function (username, infoHash, cb) {
        if(!clients.hasOwnProperty(username)){
            cb(err.serverErr);
            return;
        }
        findOneTorrentFromInfoHash(username, infoHash, function (torrent) {
            if(torrent.error) cb(torrent);
            else {
                torrent.destroy(function () {
                    db.torrent.update({
                        state: 3
                    }, {
                        where: {infoHash: infoHash}
                    }).then(function () {
                        queue.pull(username, function () {
                            cb({state: 3});
                        })
                    });
                });
            }
        });
    },
    status: function (username, cb) {
        if(!clients.hasOwnProperty(username)){
            cb(err.serverErr);
            return;
        }
        var cli = clients[username];
        var tos = {};
        for(var i=0,li=cli.torrents.length;i<li;i++){
            var torrent = {
                downloaded: cli.torrents[i].downloaded,
                downloadSpeed: cli.torrents[i].downloadSpeed,
                infoHash:  cli.torrents[i].infoHash,
                progress: cli.torrents[i].progress
            };
            tos[torrent.infoHash] = torrent;
        }
        cb({
            torrents: tos,
            downloadSpeed: cli.downloadSpeed,
            uploadSpeed: cli.uploadSpeed
        })
    },
    torrentStatus: function (username, infoHash, cb) {
        if(!clients.hasOwnProperty(username)){
            cb(err.serverErr);
            return;
        }
        var cli = clients[username];
        cli.torrents.forEach(function(e){
            if(e.infoHash === infoHash){
                var torrent = {
                    downloadSpeed: e.downloadSpeed,
                    uploadSpeed: e.uploadSpeed,
                    progress: e.progress,
                    files: []
                };
                e.files.forEach(function(f){
                    torrent.files.push({
                        name: f.name,
                        path: f.path,
                        length: f.length,
                        downloaded: f.downloaded
                    })
                });
                cb(torrent)
            }
            return;
        });
        cb(err.fileNotExist)
    }
};